package com.duang.framework.config;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.duang.framework.cache.Cache;
import com.duang.framework.cache.CacheMethod;
import com.duang.framework.cache.CacheUtils;
import com.duang.framework.service.BaseService;
import com.duang.framework.service.ServiceSingleFactory;
import com.duang.framework.util.IntrospectionUtils;

public abstract class ConfigurationUtil {

	public static void configureServiceProxyObject(
			BeanInjectionContainer beanContainer, boolean useCache)
			throws ConfigureApplicationException {
		List<Class<?>> serviceList = beanContainer.getTransactionalClassList();
		Map<Class<?>, String> serviceAlias = beanContainer.getBeanAlias();
		BeanCache beanCache = beanContainer.getBeanCache();
		for (Class<?> serviceClazz : serviceList) {
			String serviceName;
			if ((serviceName = serviceAlias.get(serviceClazz)) == null)
				serviceName = serviceClazz.getSimpleName();
			if (useCache) {
				Map<String, Cache> cacheMap = findMethodNeedToBeCached(serviceClazz);
				Object obj = beanCache.get(serviceClazz);
				if (obj == null) {
					throw new ConfigureApplicationException(
							"not found service instance");
				}

				ServiceSingleFactory.registerService(serviceName,
						(BaseService<?>) obj, cacheMap);
			} else {
				Object obj = beanCache.get(serviceClazz);
				if (obj == null) {
					throw new ConfigureApplicationException(
							"not found service instance");
				}
				ServiceSingleFactory.registerService(serviceName,
						(BaseService<?>) obj);
			}
		}

	}

	public static void configureServiceProxyObject(
			List<ServiceComponent> serviceComponentList,
			BeanContainer beanContainer, boolean useCache) {
		for (ServiceComponent serviceComponent : serviceComponentList) {
			if (useCache) {
				Map<String, Cache> cacheMap = findMethodNeedToBeCached(serviceComponent
						.getServiceImplClazz());
				ServiceSingleFactory.registerService(serviceComponent
						.getServiceName(), (BaseService<?>) beanContainer
						.findBean(serviceComponent.getServiceName()), cacheMap);
			} else {
				ServiceSingleFactory.registerService(serviceComponent
						.getServiceName(), (BaseService<?>) beanContainer
						.findBean(serviceComponent.getServiceName()));
			}
		}
	}

	public static Map<String, Cache> findMethodNeedToBeCached(
			Class<?> serviceClazz) {
		List<Method> methodList = IntrospectionUtils.getMethods(serviceClazz,
				true);
		Map<String, Boolean> usedMap = new HashMap<String, Boolean>();
		Map<String, Cache> methodMap = new HashMap<String, Cache>();
		for (Method method : methodList) {
			if (method.isAnnotationPresent(CacheMethod.class)) {
				String methodKey = IntrospectionUtils
						.getMethodSignKeyInClass(method);
				if (!usedMap.containsKey(methodKey)) {
					CacheMethod cacheMethod = method
							.getAnnotation(CacheMethod.class);
					Cache cache = CacheUtils.getCacheMethodCacheByAnnotation(
							methodKey, cacheMethod);
					methodMap.put(methodKey, cache);
					if (SystemConfiguration.isDedug()) {
						System.out.println("method:" + method + "----cache:"
								+ cache);
					}
					usedMap.put(methodKey, Boolean.TRUE);
				}
			}
		}
		return methodMap;
	}

}
